package com.anxin.act.busFlow.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.anxin.act.busFlow.dao.WfBusNodeDao;
import com.anxin.act.busFlow.dao.WfBusNodeEvolveDao;
import com.anxin.act.busFlow.dto.AddInvestDTO;
import com.anxin.act.busFlow.entity.*;
import com.anxin.act.busFlow.inter.SwitchBusStatus;
import com.anxin.act.config.entity.WfApplyForm;
import com.anxin.act.config.service.WfApplyFormService;
import com.anxin.act.process.dao.ActProcessDao;
import com.anxin.act.process.service.ProcessEndService;
import com.anxin.act.task.dao.ActTaskDao;
import com.anxin.act.utils.ActProcessUtils;
import com.anxin.act.utils.ActUtils;
import com.anxin.common.utils.DateUtils;
import com.anxin.common.utils.dict.DictUtils;
import com.anxin.common.utils.sys.DeptUtils;
import com.anxin.common.utils.sys.RoleUtils;
import com.anxin.common.utils.sys.UserUtils;
import com.anxin.framework.redis.MqProducer;
import com.anxin.framework.web.entity.AjaxResult;
import com.anxin.framework.web.service.BaseService;
import com.anxin.sys.file.dao.FileBaseDao;
import com.anxin.sys.file.entity.FileBase;
import com.anxin.sys.file.service.FileBaseService;
import com.anxin.sys.filefolder.entity.FileFolder;
import com.anxin.sys.filefolder.service.FileFolderService;
import com.anxin.sys.message.utils.SendMessageUtils;
import com.anxin.sys.system.entity.SysDept;
import com.anxin.sys.system.entity.SysUser;
//import io.swagger.annotations.ApiOperation;
import org.activiti.engine.history.HistoricProcessInstance;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;

import java.util.*;

/**
 * 业务节点Service业务层处理
 *
 * @author jbs
 * @date 2020-04-15
 */
@Service
public class WfBusNodeService extends BaseService<WfBusNodeDao, WfBusNode> {

    private static Logger logger = LoggerFactory.getLogger("sys-error");

    @Autowired
    private WfBusNodeDao wfBusNodeDao;

    @Autowired
    private WfConfigFlowService wfConfigFlowService;

    @Autowired
    private WfConfigNodeService wfConfigNodeService;

    @Autowired
    private WfBusNodeEvolveService wfBusNodeEvolveService;

    @Autowired
    private WfApplyFormService wfApplyFormService;

    @Autowired
    private FileFolderService fileFolderService;

    @Autowired
    private FileBaseService fileBaseService;

    @Autowired
    private FileBaseDao fileBaseDao;

    @Autowired
    ApplicationContext context;

    @Autowired
    private MqProducer mqProducer;

    @Autowired
    private ActProcessDao actProcessDao;

    @Autowired
    private ProcessEndService processEndService;

    @Autowired
    private WfBusRoundService wfBusRoundService;

    @Autowired
    private ActTaskDao actTaskDao;

    @Autowired
    private WfBusNodeEvolveDao wfBusNodeEvolveDao;


    private Map<String,Object> switchBusStatusImplMap = new HashMap<>();

    /**
     * 构造方法
     */
    public WfBusNodeService(){
        // 项目
        switchBusStatusImplMap.put("deal","dealBaseService");
        // 基金
        switchBusStatusImplMap.put("fund","fundBaseService"); // 已改最新
    }


    /**
     * 根据ID查询wfBusNode记录
     *
     * @param id
     * @return
     */
    public WfBusNode get(String id) {
        WfBusNode wfBusNode = super.get(id);
        //查询是否可以启动流程等其他信息
        if (wfBusNode != null){
            this.initNodeInfo(wfBusNode);
        }
        return wfBusNode;
    }


    /**
     * 查询是否可以启动流程等其他信息
     *
     * @param wfBusNode
     */
    public WfBusNode initNodeInfo(WfBusNode wfBusNode) {
        WfConfigNode wfConfigNode = wfConfigNodeService.getById(wfBusNode.getNodeId());

        // 是否有权限查看节点
        wfBusNode.setViewNode(wfConfigNode.getViewRole() == null || wfConfigNode.getViewRole().size() == 0 || RoleUtils.currentUserRole(wfConfigNode.getViewRole()));

        // 是否有权限启动流程
        boolean startRole = RoleUtils.currentUserRole(wfConfigNode.getStartRole());
        boolean startDept = DeptUtils.currentUserDept(wfConfigNode.getStartDept());
        wfBusNode.setStartProcess(((
                wfConfigNode.getStartRole() == null || wfConfigNode.getStartRole().size() == 0)
                && (wfConfigNode.getStartDept() == null || wfConfigNode.getStartDept().size() == 0))
                || startRole
                || startDept);

        // 是否可以豁免
        wfBusNode.setImmunity(RoleUtils.currentUserRole(wfConfigNode.getImmunityRole()));

        // 是否可以再次启动
        wfBusNode.setRestart(this.checkRestart(wfBusNode, wfConfigNode));

        // 获取节点要上传的附件
        wfBusNode.setFileList(this.getCheckFileBaseList(wfConfigNode, wfBusNode));

        // 是否需要操作按钮
        wfBusNode.setOperation(wfConfigNode.getOperation());

        // 是否可以编辑项目表单
        wfBusNode.setEditNode(this.getEditNode(wfConfigNode,wfBusNode));

        return wfBusNode;
    }

    /**
     * 判断是否可以编辑节点
     * @param wfConfigNode
     * @param wfBusNode
     * @return
     */
    public boolean getEditNode(WfConfigNode wfConfigNode,WfBusNode wfBusNode){
        if (wfConfigNode != null && wfConfigNode.getEditRole() != null &&  wfConfigNode.getEditRole().size() > 0 && "deal".equals(wfBusNode.getBusType())){
            List<String> dealRole = wfBusNodeDao.findDealRole(wfConfigNode.getEditRole().toJavaList(String.class), UserUtils.getUser().getId(), wfBusNode.getBusId());
            if (dealRole.size() == 0){
                return false;
            }
        }
        return true;
    }


    /**
     * 获取节点要上传的附件
     *
     * @param wfConfigNode
     * @param wfBusNode
     * @return
     */
    public List<FileBase> getCheckFileBaseList(WfConfigNode wfConfigNode, WfBusNode wfBusNode) {
        List<FileBase> resFileList = new ArrayList<>();
        // 获取必填上传附件
        if (wfConfigNode.getCheckFile() != null) {
            for (int i = 0; i < wfConfigNode.getCheckFile().size(); i++) {
                // 默认配置的ID
                String dirId = wfConfigNode.getCheckFile().getString(i);
                FileBase fileBase = this.getUploadedFile(dirId, wfBusNode,wfConfigNode);
                if(fileBase != null){
                    fileBase.setType("1");
                    resFileList.add(fileBase);
                }
            }
        }
        // 获取选填上传附件
        if (wfConfigNode.getOptionalFile() != null) {
            for (int i = 0; i < wfConfigNode.getOptionalFile().size(); i++) {
                // 默认配置的ID
                String dirId = wfConfigNode.getOptionalFile().getString(i);
                FileBase fileBase = this.getUploadedFile(dirId, wfBusNode,wfConfigNode);
                if(fileBase != null){
                    fileBase.setType("2");
                    resFileList.add(fileBase);
                }
            }
        }
        // 去重
        List<FileBase> fileBases = this.removeDuplicateOutputField(resFileList);
        return fileBases;
    }

    /**
     * 根据resFileList中对象某些字段去重
     * @param resFileList 需要去重的集合
     * @return 返回去重后的list
     */
    private static List<FileBase> removeDuplicateOutputField(List<FileBase> resFileList) {
        Set<FileBase> set = new TreeSet<>((o1, o2) -> {
            int compareToResult = 1;//==0表示重复
            //根据需求添加StringUtils.equals(o1.getDirectoryName(), o2.getDirectoryName()) ；
            if(StringUtils.equals(o1.getDirectoryName(), o2.getDirectoryName())) {
                compareToResult = 0;
            }
            return compareToResult;
        });
        set.addAll(resFileList);
        return new ArrayList<>(set);
    }

    private FileBase getUploadedFile(String dirId, WfBusNode wfBusNode,WfConfigNode wfConfigNode){
        FileFolder fileFolder = fileFolderService.getById(dirId);
        if (fileFolder != null) {
            FileBase fileBase = new FileBase();
            if (!"N".equals(wfConfigNode.getBringAccessories())){
                fileBase = this.getUploadedFiles(fileFolder.getId(),wfBusNode.getBusId());
            }
            fileBase.setFileSource(fileBase.getId());
            fileBase.setId("");
            fileBase.setDirectoryId(fileFolder.getId());
            fileBase.setBusinessId(wfBusNode.getBusId());
            fileBase.setDirectoryName(fileFolder.getName());
            return fileBase;
        }
        return null;
    }

    /**
     * 查询已经上传的附件
     * @param folderId 目录ID
     * @param busId 业务数据ID，例如项目ID,基金ID
     * @return
     */
    public FileBase getUploadedFiles(String folderId,String busId){
        FileBase fileBase = fileBaseDao.findByDirectoryIdAndBusinessId(folderId, busId);
        if (fileBase == null){
            return new FileBase();
        }

        // 设置文件来源字段，这个字段不为空不会沉淀到文档库
        if (StringUtils.isBlank(fileBase.getFileSource())){
            fileBase.setFileSource(fileBase.getId());
        }

        return fileBase;
    }

    /**
     * 是否可以再次启动流程
     *
     * @param wfBusNode
     * @param wfConfigNode
     * @return
     */
    public boolean checkRestart(WfBusNode wfBusNode, WfConfigNode wfConfigNode) {
        if (wfConfigNode.getRestart() == null || wfConfigNode.getRestart().contains(wfBusNode.getActStatus())) {
            return true;
        } else if ("Z".equals(wfBusNode.getActStatus()) || "W".equals(wfBusNode.getActStatus())) {
            return true;
        }
        return false;
    }


    /**
     * 查询业务节点列表
     *
     * @param wfBusNode 业务节点
     * @return 业务节点
     */
    public List<WfBusNode> findList(WfBusNode wfBusNode) {
        return wfBusNodeDao.findList(wfBusNode);
    }

    /**
     * 初始化数据
     * @param busType
     * @param busId
     */
    @Transactional(readOnly = false)
    public void init(String busType,String busId,String dataType,String userId,String busStatus){
        WfBusNode wfBusNode = new WfBusNode();
        wfBusNode.setParentNodeId("0");
        wfBusNode.setBusType(busType);
        wfBusNode.setBusId(busId);
        wfBusNode.setDataType(dataType);
        this.init(wfBusNode,busStatus);
    }

    /**
     * 获取流程部门ID
     * @param wfConfigFlow
     * @return
     */
    public String getDeptId(WfConfigFlow wfConfigFlow,String busId){
        busId = com.anxin.common.utils.StringUtils.symbolHandler(busId);
        String personCharge = null;

        if ("deal".equals(wfConfigFlow.getBusType())){
            personCharge = actTaskDao.getDealPersonCharge(busId);

        }else if ("fund".equals(wfConfigFlow.getBusType())){
            personCharge = actTaskDao.getFundPersonCharge(busId);
        }

        if (StringUtils.isNotBlank(personCharge)){
            return UserUtils.getUser(personCharge).getDeptId();
        }

        return UserUtils.getUser().getDeptId();
    }


    /**
     * 获取需要使用的流程
     * @param wfConfigFlow
     * @param deptId
     * @return
     */
    public List<WfConfigFlow> findWorkFlowList(WfConfigFlow wfConfigFlow,String deptId){
        if (!"0".equals(deptId)){
            wfConfigFlow.setDeptId(deptId);
        }else {
            wfConfigFlow.setDeptId(null);
        }
        //查询应该使用的流程配置
        List<WfConfigFlow> wfFlowList = wfConfigFlowService.findList(wfConfigFlow);

        if (wfFlowList.size() == 0 && !"0".equals(deptId)){
            SysDept sysDept = DeptUtils.get(deptId);
            if (sysDept != null){
                return this.findWorkFlowList(wfConfigFlow,sysDept.getParentId());
            }
        }

        return wfFlowList;
    }


    /**
     * 初始化业务节点
     *
     * @param wfBusNode
     * @return
     */
    @Transactional(readOnly = false)
    public List<WfBusNode> init(WfBusNode wfBusNode,String busStatus) {
        WfConfigFlow wfConfigFlow = new WfConfigFlow();
        // 业务类型 项目/基金
        wfConfigFlow.setBusType(wfBusNode.getBusType());
        // 数据类型 例:股权项目/债权项目
        wfConfigFlow.setBusDataType(wfBusNode.getDataType());
        //查询应该使用的流程配置
        String deptId = this.getDeptId(wfConfigFlow,wfBusNode.getBusId());
        List<WfConfigFlow> wfFlowList = this.findWorkFlowList(wfConfigFlow,deptId);

        List<WfConfigNode> wfConfigNodeList = new ArrayList<WfConfigNode>();

        if (wfFlowList.size() > 0) {
            WfConfigNode wfConfigNode = new WfConfigNode();
            wfConfigNode.setFlowId(wfFlowList.get(0).getId());
            wfConfigNode.setNodeType("first");
            //查询该配置下的节点
            wfConfigNodeList = wfConfigNodeService.findList(wfConfigNode);

            this.saveNode(wfBusNode.getBusType(), wfBusNode.getBusId(), wfConfigNodeList);
        }

        List<WfBusNode> nodeList = this.findList(wfBusNode);

        //保存当前业务的当前节点
        if (wfConfigNodeList.size() > 0) {
            wfBusNodeEvolveService.initByBusNode(wfConfigNodeList,busStatus,wfBusNode.getBusId(),wfBusNode.getBusType());
        }
        return nodeList;
    }

    /**
     * 保存节点
     * @param roundId
     * @param busType
     * @param busId
     * @param wfConfigNodeList
     */
    public WfBusNode saveNode(String roundId, String busType, String busId, List<WfConfigNode> wfConfigNodeList) {
        WfBusNode firstNode = null;

        for (WfConfigNode wfConfigNode : wfConfigNodeList) {
            // 复制wfConfigNode表中需要的字段
            WfBusNode wfBusNode = new WfBusNode(wfConfigNode);
            wfBusNode.setBusId(busId);
            wfBusNode.setBusType(busType);
            wfBusNode.setRoundId(roundId);

            // 是否最新一次
            wfBusNode.setLatest("Y");
            // 重启的次数
            wfBusNode.setRestartNum(1);
            // 审批状态 默认为未启动
            wfBusNode.setActStatus("N");

            this.save(wfBusNode);

            //保存子节点
            if (wfConfigNode.getChildren() != null) {
                this.saveNode(roundId,busType, busId, wfConfigNode.getChildren());
            }
            if (firstNode == null){
                firstNode = wfBusNode;
            }
        }
        return firstNode;
    }

    /**
     * 讲 wfConfigNode表的数据复制到  wfBusNode
     *
     * @param busType
     * @param busId
     * @param wfConfigNodeList
     */
    @Transactional(readOnly = false)
    public void saveNode(String busType, String busId, List<WfConfigNode> wfConfigNodeList) {
        this.saveNode(null,busType,busId,wfConfigNodeList);
    }

    /**
     * 获取当前关注的二级节点
     *
     * @param nodeList
     */
    public String getCurrentChildNode(List<WfBusNode> nodeList) {
        for (int i = nodeList.size(); i > 0; i--) {
            WfBusNode wfBusNode = nodeList.get(i - 1);
            // 待审批则返回当前节点
            if ("D".equals(wfBusNode.getActStatus())) {
                return wfBusNode.getId();
            }
            if ("W".equals(wfBusNode.getActStatus())) {
                return wfBusNode.getId();
            }
        }
        return nodeList.size() > 0 ? nodeList.get(0).getId() : "";
    }

    /**
     * 获取form表单组件的地址
     *
     * @return
     */
    public AjaxResult getNodeFormUrl(WfBusNode wfBusNode) {
        AjaxResult ajaxResult = AjaxResult.success();
        if ("dev".equals(wfBusNode.getFormType())) {
            WfApplyForm wfApplyForm = wfApplyFormService.get(wfBusNode.getFormId());
            ajaxResult.setData(wfApplyForm.getPath());
        }else if ("form".equals(wfBusNode.getFormType())){
            ajaxResult.setData("@/views/dev/form/base/form");
        }else if("defined".equals(wfBusNode.getFormType())){
            // 自定义表单
            ajaxResult.setData("@/views/system/desform/release/onlineForm");
//            ajaxResult.setData("@/views/system/desform/release/onlineTestPageDialog");
        } else if ("design".equals(wfBusNode.getFormType())) {
            // 表单设计
            ajaxResult.setData("@/views/system/desform/formTemplet/formTemplet");
        }
        return ajaxResult;
    }

    /**
     * 绑定dataId
     *
     * @param id     wfBusNode表的Id
     * @param dataId 数据ID
     * @return
     */
    @Transactional(readOnly = false)
    public AjaxResult bindingDataId(String id, String dataId) {
        if(id != null && dataId != null){
            wfBusNodeDao.bindingDataId(id, dataId);
        }
        return AjaxResult.success();
    }

    /**
     * 再次启动
     *
     * @param id wfBusNode表的ID
     * @return
     */
    @Transactional(readOnly = false)
    public AjaxResult restart(String id) {
        WfBusNode wfBusNode = wfBusNodeDao.getLastNode(id);
        wfBusNodeDao.updateLatest(wfBusNode);

        wfBusNode.setId(null);
        wfBusNode.setRestartNum(wfBusNode.getRestartNum() + 1);
        wfBusNode.setActId(null);
        wfBusNode.setActStatus("N");
        wfBusNode.setDataId(null);
        super.save(wfBusNode);
        return AjaxResult.success(wfBusNode);
    }

    /**
     * 获取节点审批的历史记录
     *
     * @param id
     * @return
     */
    public AjaxResult<List<WfBusNode>> getHistoryApproval(String id) {
        return AjaxResult.success(wfBusNodeDao.getHistoryApproval(id));
    }

    /**
     * 根据nodeId查询记录
     *
     * @param nodeId
     * @return
     */
    public WfBusNode getByNodeId(String nodeId,String busId) {
        WfBusNode wfBusNode = new WfBusNode();
        if(nodeId != null && busId != null){
            wfBusNode = wfBusNodeDao.getByNodeId(nodeId,busId);
        }
        return wfBusNode;
    }

    /**
     * 获取流程的一级节点
     *
     * @param id
     * @return
     */
    public WfBusNode getNextNode(String id) {
        WfBusNodeEvolve wfBusNodeEvolve = wfBusNodeEvolveService.get(id);
        WfBusNode wfBusNodeQuery = new WfBusNode();
        wfBusNodeQuery.setParentNodeId("0");
        wfBusNodeQuery.setBusId(wfBusNodeEvolve.getBusId());
        wfBusNodeQuery.setLatest("Y");
        wfBusNodeQuery.setRoundId(wfBusNodeEvolve.getRoundId());
        List<WfBusNode> wfBusNodeList = wfBusNodeDao.findList(wfBusNodeQuery);

        WfBusNode resWfBusNode = wfBusNodeList.get(wfBusNodeList.size() - 1);
        for (int i = wfBusNodeList.size(); i > 0; i--) {
            if (wfBusNodeList.get(i - 1).getNodeId().equals(wfBusNodeEvolve.getNodeId())) {
                return resWfBusNode;
            }
            resWfBusNode = wfBusNodeList.get(i - 1);
        }

        return resWfBusNode;

    }

    /**
     * 根据节点ID和业务ID查询记录
     *
     * @param nodeId 节点ID
     * @param busId  业务ID
     * @return
     */
    public List<WfBusNode> findListByNodeId(String nodeId, String busId) {
        WfBusNode wfBusNode = new WfBusNode();
        wfBusNode.setNodeId(nodeId);
        wfBusNode.setBusId(busId);
        return this.findList(wfBusNode);
    }

    /**
     * 根据业务ID校验节点是否可以提交下一阶段
     * @param busId 一级节点ID
     * @return
     */
    //@ApiOperation(value="根据业务ID校验节点是否可以提交下一阶段" ,notes="作者:刘翔宇")
    public AjaxResult checkCommitNextNodeByBusId(String busId){
        WfBusNodeEvolve wfBusNodeEvolve = wfBusNodeEvolveService.getLastNodeByBusId(busId);
        return this.checkCommitNextNode(wfBusNodeEvolve.getId());
    }

    /**
     * 获取未完成节点
     * @param nodeId 节点ID
     * @param busId 业务ID
     * @return
     */
    public List<String> getNotThroughNode(String nodeId, String busId){
        List<String> notThroughNode = new ArrayList<>();
        JSONArray relyNode = null;

        WfConfigNode wfConfigNode = wfConfigNodeService.get(nodeId);
        // 获取下一节点的依赖节点
        if (wfConfigNode != null) {
            relyNode = wfConfigNode.getRelyNode();
        }

        if (relyNode != null) {
            // 查询所有依赖的节点
            for (int i = 0; i < relyNode.size(); i++) {
                // 查询依赖节点的所有审批记录
                String relyNodeId = relyNode.getString(i);
                List<WfBusNode> relyNodeList = this.findListByNodeId(relyNodeId, busId);
                // 节点是否完成
                boolean isThrough = false;
                // 节点的名称
                String nodeName = null;

                for (int j = 0; j < relyNodeList.size(); j++) {
                    WfBusNode node = relyNodeList.get(j);
                    nodeName = node.getWfConfigNode().getNodeName();
                    if (StringUtils.isNotBlank(node.getProcessKey())){
                        boolean through = ActUtils.isThrough(node.getActStatus());
                        if (through) {
                            isThrough = true;
                        }
                    }else {
                        if (StringUtils.isNotBlank(node.getDataId())){
                            isThrough = true;
                        }
                    }

                }

                if (!isThrough) {
                    notThroughNode.add(nodeName);
                }
            }

        }
        return notThroughNode;

    }


    /**
     * 校验节点是否可以提交下一阶段
     *
     * @param nodeId 一级节点ID
     * @return 依赖但没有完成的节点名称
     */
    public AjaxResult checkCommitNextNode(String nodeId) {

        WfBusNode nextNode = this.getNextNode(nodeId);

        // 没有审批通过的依赖节点
        List<String> notThroughNode = new ArrayList<>();
        if (nextNode != null){
            notThroughNode = this.getNotThroughNode(nextNode.getNodeId(),nextNode.getBusId());
        }

        AjaxResult ajaxResult = AjaxResult.success(notThroughNode);
        // 下一节点
        ajaxResult.put("nextNode", nextNode);

        return ajaxResult;
    }

    /**
     * 提交下一节点
     *
     * @param id
     * @return
     */
    @Transactional(readOnly = false)
    public AjaxResult commitNextNode(String id) {
        WfBusNodeEvolve wfBusNodeEvolve = wfBusNodeEvolveService.get(id);
        WfBusNode nextNode = this.getNextNode(id);
        wfBusNodeEvolveService.saveByBusNode(nextNode,wfBusNodeEvolve.getRoundId());

        // 项目切换阶段时发送提醒
        this.sendMessage(wfBusNodeEvolve, nextNode);

        // 修改业务状态
        this.switchBusStatus(nextNode);

        // 修改项目阶段
        String dealStage = DictUtils.getDictValue(nextNode.getWfConfigNode().getNodeName(), "deal_stage");
        if(StringUtils.isNotBlank(dealStage) && StringUtils.isNotBlank(nextNode.getBusId())){
            dao.updateDealStage(nextNode.getBusId(),dealStage);
        }
        return AjaxResult.success(wfBusNodeEvolve);
    }

    /**
     * 切换业务状态
     *
     * @param nextNode
     */
    public void switchBusStatus(WfBusNode nextNode) {
        // 如果不是首轮投资则不改状态
        String roundId = nextNode.getRoundId();
        if (StringUtils.isNotBlank(roundId)){
            WfBusRound wfBusRound = wfBusRoundService.get(roundId);
            if (wfBusRound != null && wfBusRound.getNum() != 1){
                return;
            }
        }

        WfConfigNode wfConfigNode = wfConfigNodeService.get(nextNode.getNodeId());
        if (StringUtils.isNotBlank(wfConfigNode.getBusStatus())) {
            Map<String, SwitchBusStatus> beansMap = context.getBeansOfType(SwitchBusStatus.class);
            beansMap.get(switchBusStatusImplMap.get(nextNode.getBusType())).switchStatus(nextNode.getBusId(),wfConfigNode.getBusStatus());
        }
    }


    /**
     * 项目节点切换时发送提醒
     *
     * @param wfBusNodeEvolve 上一个节点
     * @param nextNode        下一个几点
     */
    public void sendMessage(WfBusNodeEvolve wfBusNodeEvolve, WfBusNode nextNode) {
        try {
            JSONObject messageJson = new JSONObject();
            wfBusNodeEvolve = wfBusNodeEvolveService.get(wfBusNodeEvolve.getId());

            // 业务名称
            messageJson.put("busName", this.getBusName(nextNode.getBusType(), nextNode.getBusId()));

            // 上一个节点的滞留时间
            messageJson.put("residenceTime", DateUtils.timeStampToDate(wfBusNodeEvolve.getStrandedTime()));

            // 操作用户
            SysUser user = UserUtils.getUser();
            messageJson.put("createBy", user.getNickName());

            // 当前节点名称
            WfConfigNode nextWfConfigNode = wfConfigNodeService.get(nextNode.getNodeId());
            messageJson.put("nodeName", nextWfConfigNode.getNodeName());

            // 上一个节点的名称
            WfConfigNode beforeNode = wfConfigNodeService.get(wfBusNodeEvolve.getNodeId());
            messageJson.put("beforeNode", beforeNode.getNodeName());

            // 发送消息
            SendMessageUtils.sendMessage("phaseSwitch", nextNode.getBusType(), nextNode.getBusId(), messageJson);
        } catch (Exception e) {
            logger.error("项目节点切换时发送提醒异常",e);
        }


    }

    /**
     * 获取业务数据名称
     *
     * @param busType 业务类型
     * @param busId   业务ID
     * @return 业务数据名称
     */
    public String getBusName(String busType, String busId) {
        WfBusDataService wfBusDataService = null;
        Map<String, WfBusDataService> wfBusDataImplMap = context.getBeansOfType(WfBusDataService.class);
        if ("deal".equals(busType)) {
            wfBusDataService = wfBusDataImplMap.get("dealBaseService");
        } else if ("fund".equals(busType)) {
            wfBusDataService = wfBusDataImplMap.get("fundBaseService");
        }
        if (wfBusDataService != null) {
            return wfBusDataService.getBusName(busId);
        }

        return "";
    }

    /**
     * 保存项目进展
     *
     * @param id wf_bus_node 表ID
     */
    public void sendEvent(String id, String title) {
        WfBusNode wfBusNode = wfBusNodeDao.getById(id);
        if ("deal".equals(wfBusNode.getBusType())) {


            JSONObject eventJson = new JSONObject();
            eventJson.put("type", "LC");
            eventJson.put("title", title);

            //content.append("启动次数:第" +wfBusNode.getRestartNum()+ "次"+ "</br>");
            JSONArray contentArray = new JSONArray();
            JSONObject status = new JSONObject();
            status.put("languageCode","审批状态");
            status.put("data",DictUtils.getDictLabel(wfBusNode.getActStatus(), "work_flow_status", "未启动"));
            status.put("dataLanguage","Y");
            contentArray.add(status);

            // 申请人
            String applyUser = null;
            // 申请时间
            String applyTime = null;

            if (wfBusNode != null && StringUtils.isNotBlank(wfBusNode.getActId())){
                HistoricProcessInstance hiProcessInstance = ActProcessUtils.getHiProcessInstance(wfBusNode.getActId());
                applyUser = UserUtils.findByUserNameContainsDelete(hiProcessInstance.getStartUserId()).getNickName();
                applyTime = DateUtils.dateTime(hiProcessInstance.getStartTime());

            }else {
                applyUser = UserUtils.getUser().getNickName();
                applyTime = DateUtils.getDate();
            }

            JSONObject applyUserJson = new JSONObject();
            applyUserJson.put("languageCode","申请人");
            applyUserJson.put("data",applyUser);
            applyUserJson.put("dataLanguage","N");
            contentArray.add(applyUserJson);

            JSONObject applyTimeJson = new JSONObject();
            applyTimeJson.put("languageCode","申请时间");
            applyTimeJson.put("data",applyTime);
            applyTimeJson.put("dataLanguage","N");
            contentArray.add(applyTimeJson);

            eventJson.put("dealEventContentList", contentArray);
            eventJson.put("dealId", wfBusNode.getBusId());
            eventJson.put("busId", wfBusNode.getId());
            eventJson.put("dataId", wfBusNode.getActId());
            eventJson.put("component", "@/views/act/process/processInfoForm");

            mqProducer.sendMessageByBeanName("dealEventService", eventJson.toJSONString());
        }
    }

    /**
     * 获取当前节点表单中上传的附件
     * @param id wf_bus_node表中的ID
     * @return 表单中上传的附件集合
     */
    public List<FileBase> getFileById(String id){
        WfBusNode wfBusNode = dao.getById(id);
        if (wfBusNode != null){
            return fileBaseService.findList(wfBusNode.getDataId(), null);
        }else {
            return new ArrayList<>();
        }

    }

    /**
     * 流程豁免
     * @param id wf_bus_node表ID
     * @return
     */
    @Transactional(readOnly = false)
    public AjaxResult immunityProcess(@PathVariable("id")String id){
        WfBusNode wfBusNode = new WfBusNode();
        if(id != null){
             wfBusNode = dao.getById(id);
        }
        WfConfigNode wfConfigNode = wfConfigNodeService.get(wfBusNode.getNodeId());

        if (RoleUtils.currentUserRole(wfConfigNode.getImmunityRole())){
            wfBusNodeDao.updateStatus(id,"H");

            if (StringUtils.isNotBlank(wfBusNode.getDataId())){
                String formTable = ActUtils.getFormTable(wfBusNode.getFormType(), wfBusNode.getFormId());
                processEndService.businessEnd(formTable, wfBusNode.getDataId(), null,null);
            }

            /*if (StringUtils.isNotBlank(wfBusNode.getBusId()) && StringUtils.equals("投后交接", wfConfigNode.getNodeName())) {
                DealBase project = dealBaseDao.getById(wfBusNode.getBusId());
                if (project != null) {
                    // 将项目状态更新为投后
                    project.setDealStatus("TH");
                    dealBaseService.save(project);
                    // 判断是否已初始化财务模板
                    PcwCmyInit pcwCmyInit = pcwCmyInitService.getByCompanyId(project.getCompanyId());
                    if (pcwCmyInit == null && (com.anxin.common.utils.StringUtils.equals("equity", project.getDealType()) || com.anxin.common.utils.StringUtils.equals("debt", project.getDealType()))) {
                        pcwCmyInit = new PcwCmyInit();
                        pcwCmyInit.setTypeId("10b4f3d3373d41e3b73a6e08a5f8a7f8");
                        pcwCmyInit.setCompanyId(project.getCompanyId());
                        pcwCmyInitService.save(pcwCmyInit);
                        PcwTempSysSubject pcwTempSysSubject = new PcwTempSysSubject();
                        pcwTempSysSubject.setTypeId(pcwCmyInit.getTypeId());
                        List<PcwTempSysSubject> subjects = pcwTempSysSubjectService.findList(pcwTempSysSubject);
                        pcwTempSubjectService.deleteByCompanyId(pcwCmyInit.getCompanyId());
                        for (PcwTempSysSubject sysSubject : subjects) {
                            PcwTempSubject tempSubject = new PcwTempSubject(sysSubject);
                            tempSubject.setCompanyId(pcwCmyInit.getCompanyId());
                            pcwTempSubjectService.save(tempSubject);
                        }
                    }
                }
            }*/
            return AjaxResult.success();
        }else {
            return AjaxResult.error("无权豁免");
        }
    }

    /**
     * 修改业务数据删除标记状态 如果是 2 则 改为 0
     * @param wfBusNode 节点配置信息
     */
    public void updateDataDelFlag(WfBusNode wfBusNode){
        if (StringUtils.isNotBlank(wfBusNode.getFormId()) && StringUtils.isNotBlank(wfBusNode.getFormType())){
            if (StringUtils.isNotBlank(wfBusNode.getDataId())){
                String formTable = ActUtils.getFormTable(wfBusNode.getFormType(), wfBusNode.getFormId());
                if (StringUtils.isNotBlank(formTable)){
                    Map<String, Object> dataMap = actProcessDao.selectData(com.anxin.common.utils.StringUtils.symbolHandler(formTable), wfBusNode.getDataId());
                    if (dataMap != null){
                        if ("2".equals(dataMap.get("del_flag"))){
                            actProcessDao.updateDataDelFlag(formTable,wfBusNode.getDataId());
                        }

                        if (dataMap.containsKey("act_status")){
                            actProcessDao.updateDataTable(formTable,wfBusNode.getDataId(),"W",null);
                        }
                    }

                }
            }
        }
    }

    /**
     * 根据nodeId查询审批通过的记录条数
     * @return
     */
    public int findCompleteByNodeId(String nodeId, String busId) {
        return wfBusNodeDao.findCompleteByNodeId(nodeId, busId);
    }

    /**
     * 查询应该被删除的节点
     * @return
     */
    public List<String> findDeleteNode(){
        return wfBusNodeDao.findDeleteNode();
    }

    /**
     * 获取使用的流程ID
     * @param busId
     * @return
     */
    public String getFlowId(String busId){
        return wfBusNodeDao.getFlowId(busId);
    }

    /**
     * 保存首轮投资信息
     * @param addInvestDTO
     * @return
     */
    public WfBusRound saveFirstInvest(AddInvestDTO addInvestDTO){
        WfBusRound firstInvest = wfBusRoundService.getFirstInvest(addInvestDTO.getBusId());
        if (firstInvest == null){
            firstInvest = new WfBusRound();
            firstInvest.setNum(1);
            firstInvest.setType("first");
            firstInvest.setBusId(addInvestDTO.getBusId());
        }
        firstInvest.setName(addInvestDTO.getFirstInvestName());

        wfBusRoundService.save(firstInvest);

        wfBusNodeDao.updateRoundId(firstInvest.getId(),addInvestDTO.getBusId());

        wfBusNodeEvolveDao.updateRoundId(firstInvest.getId(),addInvestDTO.getBusId());

        return firstInvest;

    }

    /**
     * 查询一级节点
     * @param wfBusNode
     * @return
     */
    @Transactional(readOnly = false)
    public AjaxResult<List<WfBusNode>> getParentNode(WfBusNode wfBusNode){
        // 查询轮次数据
        List<WfBusRound> roundList = wfBusRoundService.findByBusId(wfBusNode.getBusId());
        if (StringUtils.isBlank(wfBusNode.getRoundId())){
            if (roundList.size() > 0){
                wfBusNode.setRoundId(roundList.get(roundList.size() - 1).getId());
            }
        }

        // 查询dataType
        if(StringUtils.equals(wfBusNode.getBusType(),"deal")){
            String dataType = dao.getDataType(wfBusNode.getBusId());
            wfBusNode.setDataType(dataType);
        }


        // 查询所有一级节点
        wfBusNode.setParentNodeId("0");
        List<WfBusNode> nodeList = this.findList(wfBusNode);

        // 如果没有查询到记录，则初始化记录
        if (nodeList.size() == 0){
            nodeList = this.init(wfBusNode,wfBusNode.getDataType());
        }
        AjaxResult ajaxResult = AjaxResult.success(nodeList);


        // 查询是否配置了新增投资流程
        if (nodeList.size() > 0){
            String flowId = this.getFlowId(nodeList.get(0).getBusId());
            List<WfConfigNode> newNode = wfConfigNodeService.findByFlowId(flowId, "new");
            if (newNode.size() > 0){
                ajaxResult.put("addInvest","Y");
            }
            // 获取当前角色是否可以提交下一阶段
            WfConfigFlow wfConfigFlow = wfConfigFlowService.getById(flowId);
            if (wfConfigFlow != null) {
                String roleId = wfConfigFlow.getRoleId();
                // 处理 roleId = """" 的情况
                String nullCharacter = "";
                String isNull = "\"" + nullCharacter + "\"";
                if (!com.anxin.common.utils.StringUtils.isBlank(roleId) && !isNull.equals(roleId)) {
                    ajaxResult.put("isSubmitStage",RoleUtils.currentUserRole(JSONArray.parseArray(roleId)));
                }else{
                    ajaxResult.put("isSubmitStage",true);
                }
            }
        }

        // 当前阶段
        ajaxResult.put("currentNode",wfBusNodeEvolveService.getLatestEvolve(wfBusNode.getBusType(),wfBusNode.getBusId(),wfBusNode.getRoundId()));
        // 当前轮次ID
        ajaxResult.put("roundId",wfBusNode.getRoundId());
        // 当前所有轮次集合
        ajaxResult.put("roundList",roundList);


        return ajaxResult;
    }


    /**
     * 保存投资轮次
     * @param addInvestDTO
     * @return
     */
    @Transactional(readOnly = false)
    public AjaxResult<WfBusRound> saveInvestRound(AddInvestDTO addInvestDTO){
        String flowId = this.getFlowId(addInvestDTO.getBusId());


        if ("Y".equals(addInvestDTO.getFirstInvest())){
            this.saveFirstInvest(addInvestDTO);
        }


        WfBusRound wfBusRound = wfBusRoundService.saveNewRound(addInvestDTO,"new");
        List<WfConfigNode> wfConfigNodeList = wfConfigNodeService.findByFlowId(flowId, "new");
        WfBusNode wfBusNode = this.saveNode(wfBusRound.getId(), addInvestDTO.getBusType(), addInvestDTO.getBusId(), wfConfigNodeList);

        wfBusNodeEvolveService.saveByBusNode(wfBusNode,wfBusNode.getRoundId());
        return AjaxResult.success(wfBusRound);
    }

}
